#include <stdio.h>
#include <stdlib.h>
#include <math.h>


int main(){
    int i, ordem, j, iteracao, MaxIteracao, fila;

    scanf("%d", &ordem);
    scanf("%d", &fila);

    float *X, *Xk, erro;
    float *A, *B, *Ainicial, auxErro, auxErro1;

    X = (float *) malloc(ordem*sizeof(float));        //Parte em que faz as alocaçoes das variaveis.
    Xk = (float *) malloc(ordem*sizeof(float));       //Notando em que a matriz A é um VETOR ordem*ordem.
    A = (float *) malloc(ordem*ordem*sizeof(float));
    Ainicial = (float *) malloc(ordem*ordem*sizeof(float));
    B = (float *) malloc(ordem*sizeof(float));

    scanf("%f", &erro);
    scanf("%d", &MaxIteracao);

    for(i=0; i<ordem*ordem; i++)                      //Salva os valores da Matriz A.
        scanf("%f", &A[i]);

    for(i=0; i<ordem; i++)                      //Salva os valores da Matriz B.
        scanf("%f", &B[i]);

    for(i=0; i<ordem*ordem; i++)                      //Salva os valores da Matriz A, na auxiliar Matriz Ainicial.
        Ainicial[i] = A[i];

    for(i=0; i<ordem; i++)                       //Guarda o valor da diagonal da Matriz A na matriz X.
        X[i] = A[i*ordem+i];

    for(i=0; i<ordem; i++)                    //Calcula os novos valores da matriz A para o calculo  das iterações.
        for(j=0; j<ordem; j++){               //Onde a diagonal da matriz tem como valor o B / X(valor da diagonal)
            if(i == j)
                A[i*ordem+i] = B[i] / X[i];
            else
                A[i*ordem+j] = -(A[i*ordem+j] / X[i]);
        }

    for(i=0; i<ordem; i++)                      //Pega a matriz B (resultado) e dividi pela diagonal, para o calculo da iteraçao 0.
        X[i] = B[i] / X[i];

    iteracao = 0;
    while (iteracao < MaxIteracao){          //Repetiçao ateh o numero  de iteraçoes que foi passada pelo usuario.
        for(i=0; i<ordem; i++)               //Zera os valores da matriz Xk (k+1).
            Xk[i] = 0;

        for(i=0; i<ordem; i++)               //Faz o calculo do novo valor da Xk.
            for(j=0; j<ordem; j++){
                if(i == j)                   //Se for a diagonal, apenas soma o valor,
                    Xk[i] = Xk[i] + A[i*ordem+i];
                else                            //Senão pega o valor e multiplica pelo Xk ( valor do x antigo)
                    Xk[i] = Xk[i] + (A[i*ordem+j]*X[j]);
            }

        iteracao++;
        auxErro = 0;
        auxErro1 = 0;
        for(i=0; i<ordem; i++)
            if(fabs(Xk[i] - X[i]) > auxErro)   //Parte em que se calcula o modulo dos valores, para calcular o erro.(Numerador)
                auxErro = fabs(Xk[i] - X[i]);

        for(i=0; i<ordem; i++)
            if(fabs(Xk[i]) > auxErro1)   //Parte em que se calcula o modulo dos valores, para calcular o erro.(denominador)
                auxErro1 = fabs(Xk[i]);

        auxErro = auxErro / auxErro1;

        if(auxErro < erro)                         //Se o erro for menor que o erro que foi passado pelo usuario, acaba as iterações.
            break;

        for(i=0; i<ordem; i++)                       //Salva os valores da matriz Xk (matriz em que calcula a nova iteraçao),
            X[i] = Xk[i];                               //na matriz X (matriz com os valores antigos da iteraçao.
    }

    float Xkfinal = 0;                                      //Calculo do Xkfinal, que será o valor que resultará da conta com o valor proximo do X encontrado.
    for(i=0; i<ordem; i++)
            Xkfinal = Xkfinal + (Ainicial[fila*ordem+i] * Xk[i]);

    printf("Iterations: %d", iteracao);
    printf("\n");
    printf("RowTest: %d => [%f] =? %f", fila, Xkfinal, B[fila]);
    printf("\n");

    free(X);
    free(Xk);
    free(B);
    free(A);
    free(Ainicial);

    return 0;
}
